home *** CD-ROM | disk | FTP | other *** search
- /*
- * Help utilities.
- * Copyright (c) 1995 Markku Rossi.
- *
- * Author: Markku Rossi <mtr@iki.fi>
- */
-
- /*
- * This file is part of GNU enscript.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
- #include "gsint.h"
-
- /*
- * Static variables.
- */
-
- /* 7bit ASCII scand encodings (additions to 7bit ASCII enc). */
- static struct
- {
- int code;
- char *name;
- } enc_7bit_ascii_scands[] =
- {
- {'{', "adieresis"},
- {'|', "odieresis"},
- {'}', "aring"},
- {'[', "Adieresis"},
- {'\\', "Odieresis"},
- {']', "Aring"},
- {0, NULL},
- };
-
-
- /*
- * Prototypes for static functions.
- */
-
- static void cfg_fatal __P ((char *file, int line, char *fmt, ...));
-
-
- /*
- * Global functions.
- */
-
- void
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- message (int verbose_level, char *fmt, ...)
- #else
- message (verbose_level, va_alist)
- int verbose_level;
- va_dcl
- #endif
- {
- va_list args;
-
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- va_start (args, fmt);
- #else
- char *fmt;
-
- va_start (args);
- fmt = va_arg (args, char *);
- #endif
-
- if (quiet || verbose < verbose_level)
- return;
-
- #if HAVE_VPRINTF
- vfprintf (stderr, fmt, args);
- #else
- _doprnt (fmt, args, stderr);
- #endif
-
- va_end (args);
- }
-
-
- void
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- error (char *fmt, ...)
- #else
- error (va_alist)
- va_dcl
- #endif
- {
- va_list args;
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- va_start (args, fmt);
- #else
- char *fmt;
-
- va_start (args);
- fmt = va_arg (args, char *);
- #endif
-
- fprintf (stderr, "%s: ", program);
-
- #if HAVE_VPRINTF
- vfprintf (stderr, fmt, args);
- #else
- _doprnt (fmt, args, stderr);
- #endif
- va_end (args);
-
- fprintf (stderr, "\n");
- fflush (stderr);
- }
-
-
- void
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- fatal (char *fmt, ...)
- #else
- fatal (va_alist)
- va_dcl
- #endif
- {
- va_list args;
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- va_start (args, fmt);
- #else
- char *fmt;
-
- va_start (args);
- fmt = va_arg (args, char *);
- #endif
-
- fprintf (stderr, "%s: ", program);
-
- #if HAVE_VPRINTF
- vfprintf (stderr, fmt, args);
- #else
- _doprnt (fmt, args, stderr);
- #endif
- va_end (args);
-
- fprintf (stderr, "\n");
- fflush (stderr);
-
- exit (1);
- }
-
- #define GET_TOKEN(from) (strtok ((from), " \t\n"))
- #define GET_LINE_TOKEN(from) (strtok ((from), "\n"))
-
- #define CHECK_TOKEN() \
- if (token2 == NULL) \
- cfg_fatal (fname, line, _("missing argument: %s"), token);
-
- int
- read_config (char *path, char *file)
- {
- FILE *fp;
- char fname[512];
- char buf[4096];
- char *token, *token2;
- int line = 0;
-
- sprintf (fname, "%s/%s", path, file);
- fp = fopen (fname, "r");
- if (fp == NULL)
- return 0;
-
- while (fgets (buf, sizeof (buf), fp))
- {
- line++;
-
- if (buf[0] == '#')
- continue;
-
- token = GET_TOKEN (buf);
- if (token == NULL)
- /* Empty line. */
- continue;
-
- if (MATCH (token, "AcceptCompositeCharacters:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- accept_composites = atoi (token2);
- }
- else if (MATCH (token, "AFMPath:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (afm_path_buffer, token2);
- afm_path = afm_path_buffer;
- }
- else if (MATCH (token, "AppendCtrlD:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- append_ctrl_D = atoi (token2);
- }
- else if (MATCH (token, "Clean7Bit:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- clean_7bit = atoi (token2);
- }
- else if (MATCH (token, "DefaultEncoding:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (encoding_name_buffer, token2);
- encoding_name = encoding_name_buffer;
- }
- else if (MATCH (token, "DefaultFancyHeader:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (fancy_header_default, token2);
- }
- else if (MATCH (token, "DefaultMedia:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (media_name_buffer, token2);
- media_name = media_name_buffer;
- }
- else if (MATCH (token, "DefaultOutputMethod:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- if (MATCH (token2, "printer"))
- output_file = OUTPUT_FILE_NONE;
- else if (MATCH (token2, "stdout"))
- output_file = OUTPUT_FILE_STDOUT;
- else
- cfg_fatal (fname, line, _("illegal value \"%s\" for option %s"),
- token2, token);
- }
- else if (MATCH (token, "DownloadFont:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strhash_put (download_fonts, token2, strlen (token2) + 1, NULL,
- NULL);
- }
- else if (MATCH (token, "EscapeChar:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- escape_char = atoi (token2);
- if (escape_char < 0 || escape_char > 255)
- cfg_fatal (fname, line, _("invalid value \"%s\" for option %s"),
- token2, token);
- }
- else if (MATCH (token, "FormFeedType:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- if (MATCH (token2, "column"))
- formfeed_type = FORMFEED_COLUMN;
- else if (MATCH (token2, "page"))
- formfeed_type = FORMFEED_PAGE;
- else
- cfg_fatal (fname, line, _("illegal value \"%s\" for option %s"),
- token2, token);
- }
- else if (MATCH (token, "HighlightBarGray:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- highlight_bar_gray = atof (token2);
- }
- else if (MATCH (token, "HighlightBars:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- highlight_bars = atoi (token2);
- }
- else if (MATCH (token, "LibraryPath:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (libpath, token2);
- }
- else if (MATCH (token, "Media:"))
- {
- char *name;
- int w, h, llx, lly, urx, ury;
-
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- name = token2;
-
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- w = atoi (token2);
-
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- h = atoi (token2);
-
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- llx = atoi (token2);
-
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- lly = atoi (token2);
-
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- urx = atoi (token2);
-
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- ury = atoi (token2);
-
- add_media (name, w, h, llx, lly, urx, ury);
- }
- else if (MATCH (token, "NonPrintableFormat:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (npf_name_buf, token2);
- npf_name = npf_name_buf;
- }
- else if (MATCH (token, "PageLabelFormat:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (page_label_format_buf, token2);
- page_label_format = page_label_format_buf;
- }
- else if (MATCH (token, "PagePrefeed:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- page_prefeed = atoi (token2);
- }
- else if (MATCH (token, "Printer:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (printer_buf, token2);
- printer = printer_buf;
- }
- else if (MATCH (token, "QueueParam:"))
- {
- token2 = GET_LINE_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (queue_param, token2);
- }
- else if (MATCH (token, "SetPageDevice:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- parse_key_value_pair (pagedevice, token2);
- }
- else if (MATCH (token, "Spooler:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (spooler_command, token2);
- }
- else if (MATCH (token, "StatusDict:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- parse_key_value_pair (statusdict, token2);
- }
- else if (MATCH (token, "Underlay:"))
- {
- token2 = GET_LINE_TOKEN (NULL);
- CHECK_TOKEN ();
- underlay = xmalloc (strlen (token2) + 1);
- strcpy (underlay, token2);
- }
- else if (MATCH (token, "UnderlayAngle:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- ul_angle = atof (token2);
- ul_angle_p = 1;
- }
- else if (MATCH (token, "UnderlayFont:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- if (!parse_font_spec (token2, &ul_font, &ul_ptsize))
- cfg_fatal (fname, line, _("malformed font spec: %s"), token2);
- }
- else if (MATCH (token, "UnderlayGray:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- ul_gray = atof (token2);
- }
- else if (MATCH (token, "UnderlayPosition:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (ul_position_buf, token2);
- ul_position = ul_position_buf;
- ul_position_p = 1;
- }
- else if (MATCH (token, "UnderlayStyle:"))
- {
- token2 = GET_TOKEN (NULL);
- CHECK_TOKEN ();
- strcpy (ul_style_str_buf, token2);
- ul_style_str = ul_style_str_buf;
- }
- else
- cfg_fatal (fname, line, _("illegal option: %s"), token);
- }
- return 1;
- }
-
-
- void
- add_media (char *name, int w, int h, int llx, int lly, int urx, int ury)
- {
- MediaEntry *entry;
-
- message (2,
- "add_media: name=%s, w=%d, h=%d, llx=%d, lly=%d, urx=%d, ury=%d\n",
- name, w, h, llx, lly, urx, ury);
-
- entry = xcalloc (1, sizeof (*entry));
- entry->name = xmalloc (strlen (name) + 1);
-
- strcpy (entry->name, name);
- entry->w = w;
- entry->h = h;
- entry->llx = llx;
- entry->lly = lly;
- entry->urx = urx;
- entry->ury = ury;
-
- entry->next = media_names;
- media_names = entry;
- }
-
-
- void
- do_list_missing_characters (int *array)
- {
- int i;
- int count = 0;
-
- for (i = 0; i < 256; i++)
- if (array[i])
- {
- fprintf (stderr, "%3d ", i);
- count++;
- if (count % 15 == 0)
- fprintf (stderr, "\n");
- }
-
- if (count % 15 != 0)
- fprintf (stderr, "\n");
- }
-
-
- int
- file_existsp (char *name, char *suffix)
- {
- FileLookupCtx ctx;
-
- strcpy (ctx.name, name);
- strcpy (ctx.suffix, suffix ? suffix : "");
-
- return pathwalk (libpath, file_lookup, &ctx);
- }
-
-
- int
- paste_file (char *name, char *suffix)
- {
- char buf[512];
- char resources[512];
- FILE *fp;
- FileLookupCtx ctx;
- int pending_comment = 0;
- int line = 0;
-
- strcpy (ctx.name, name);
- strcpy (ctx.suffix, suffix ? suffix : "");
-
- if (!pathwalk (libpath, file_lookup, &ctx))
- return 0;
- fp = fopen (ctx.fullname, "r");
- if (fp == NULL)
- return 0;
-
- /* Find the end of the header. */
- #define HDR_TAG "% -- code follows this line --"
- while ((fgets (buf, sizeof (buf), fp)))
- {
- line++;
- if (strncmp (buf, HDR_TAG, strlen (HDR_TAG)) == 0)
- break;
- }
-
- /* Dump rest of file. */
- while ((fgets (buf, sizeof (buf), fp)))
- {
- line++;
-
- /*
- * Document needed resources?
- */
- #define RESOURCE_DSC "%%DocumentNeededResources:"
- #define CONT_DSC "%%+"
- if (strncmp (buf, RESOURCE_DSC, strlen (RESOURCE_DSC)) == 0)
- {
- char *cp, *cp2;
-
- strcpy (resources, buf + strlen (RESOURCE_DSC));
- pending_comment = 1;
-
- parse_resources:
- /* Register needed resources. */
- cp = GET_TOKEN (resources);
- if (cp == NULL)
- /* Get the next line. */
- continue;
-
- if (MATCH (cp, "font"))
- {
- for (cp = GET_TOKEN (NULL); cp; cp = GET_TOKEN (NULL))
- /* Is this font already known? */
- if (!strhash_get (res_fonts, cp, strlen (cp) + 1,
- (void **) &cp2))
- {
- /* Not it is not, we must include this resource. */
- fprintf (ofp, "%%%%IncludeResource: font %s\n", cp);
-
- /*
- * And register that this resource is needed in
- * this document.
- */
- strhash_put (res_fonts, cp, strlen (cp) + 1, NULL, NULL);
- }
-
- /* Do not pass this DSC row to the output. */
- continue;
- }
- else
- /* Unknown resource, ignore. */
- continue;
- }
- else if (pending_comment
- && strncmp (buf, CONT_DSC, strlen (CONT_DSC)) == 0)
- {
- strcpy (resources, buf + strlen (CONT_DSC));
- goto parse_resources;
- }
- else
- pending_comment = 0;
-
- /*
- * `%Format' directive?
- */
- #define DIRECTIVE_FORMAT "%Format:"
- if (strncmp (buf, DIRECTIVE_FORMAT, strlen (DIRECTIVE_FORMAT)) == 0)
- {
- int i, j;
- char name[256];
- char *cp, *cp2;
- errno = 0;
-
- /* Skip the leading whitespace. */
- for (i = strlen (DIRECTIVE_FORMAT); buf[i] && isspace (buf[i]); i++)
- ;
- if (!buf[i])
- fatal (_("%s:%d: %%Format: no name"), ctx.fullname, line);
-
- /* Copy name. */
- for (j = 0;
- j < sizeof (name) - 1 && buf[i] && !isspace (buf[i]);
- i++)
- name[j++] = buf[i];
- name[j] = '\0';
-
- if (j >= sizeof (name) - 1)
- fatal (_("%s:%d: %%Format: too long name, maxlen=%d"),
- ctx.fullname, line, sizeof (name) - 1);
-
- /* Find the start of the format string. */
- for (; buf[i] && isspace (buf[i]); i++)
- ;
-
- /* Find the end. */
- j = strlen (buf);
- for (j--; isspace (buf[j]) && j > i; j--)
- ;
- j++;
-
- message (2, "%%Format: %s %.*s\n", name, j - i, buf + i);
-
- cp = xmalloc (j - i + 1);
- memcpy (cp, buf + i, j - i);
- cp[j - i] = '\0';
-
- strhash_put (user_strings, name, strlen (name) + 1, cp,
- (void **) &cp2);
- if (cp2)
- fatal (_("%s:%d: %%Format: name \"%s\" is already defined"),
- ctx.fullname, line, name);
-
- /* All done with the `%Format' directive. */
- continue;
- }
-
- /*
- * `%HeaderHeight' directive?
- */
- #define DIRECTIVE_HEADERHEIGHT "%HeaderHeight:"
- if (strncmp (buf, DIRECTIVE_HEADERHEIGHT,
- strlen (DIRECTIVE_HEADERHEIGHT)) == 0)
- {
- int i;
-
- /* Find the start of the pts argument. */
- for (i = strlen (DIRECTIVE_HEADERHEIGHT);
- buf[i] && !isspace (buf[i]); i++)
- ;
- if (!buf[i])
- fatal (_("%s:%d: %%HeaderHeight: no argument"), ctx.fullname, line);
-
- d_header_h = atoi (buf + i);
- message (2, "%%HeaderHeight: %d\n", d_header_h);
- continue;
- }
-
- /*
- * `%FooterHeight' directive?
- */
- #define DIRECTIVE_FOOTERHEIGHT "%FooterHeight:"
- if (strncmp (buf, DIRECTIVE_FOOTERHEIGHT,
- strlen (DIRECTIVE_FOOTERHEIGHT)) == 0)
- {
- int i;
-
- /* Find the start of the pts argument. */
- for (i = strlen (DIRECTIVE_FOOTERHEIGHT);
- buf[i] && !isspace (buf[i]); i++)
- ;
- if (!buf[i])
- fatal (_("%s:%d: %%FooterHeight: no argument"), ctx.fullname, line);
-
- d_footer_h = atoi (buf + i);
- message (2, "%%FooterHeight: %d\n", d_footer_h);
- continue;
- }
-
- /* Nothing special, just copy it to the output. */
- fputs (buf, ofp);
- }
-
- fclose (fp);
-
- return 1;
- }
-
-
- int
- parse_font_spec (char *spec, char **name_return, double *size_return)
- {
- int i;
- char *cp;
-
- /* The `name@ptsize' format? */
- cp = strchr (spec, '@');
- if (cp)
- {
- i = cp - spec;
- if (cp[1] == '\0')
- /* No ptsize after '@'. */
- return 0;
-
- *size_return = atof (cp + 1);
- }
- else
- {
- /* Old `nameptsize' format. */
- i = strlen (spec) - 1;
- if (i <= 0 || !ISNUMBERDIGIT (spec[i]))
- return 0;
-
- for (i--; i >= 0 && ISNUMBERDIGIT (spec[i]); i--)
- ;
- i++;
- *size_return = atof (spec + i);
- }
-
- *name_return = (char *) xcalloc (1, i + 1);
- strncpy (*name_return, spec, i);
-
- message (2, "parse_font_spec(): name=%.*s, size=%g\n", i, *name_return,
- *size_return);
- return 1;
- }
-
-
- void
- read_font_info (void)
- {
- AFMFont font;
- int cached = 1;
- int i;
- unsigned int enc_flags = 0;
-
- message (1, _("reading AFM info for font \"%s\"\n"), Fname);
-
- if (accept_composites)
- enc_flags = AFM_ENCODE_ACCEPT_COMPOSITES;
-
- /* Open font */
- if (!strhash_get (afm_cache, Fname, strlen (Fname), (void **) &font))
- {
- AFMError error;
- char buf[256];
-
- /* Couldn't find it from our cache, open it from disk. */
- error = afm_open_font (afm, AFM_I_COMPOSITES, Fname, &font);
- if (error != AFM_SUCCESS)
- {
- #define COUR "Courier"
- /*
- * Do not report failures for "Courier*" fonts because
- * AFM library's default font will fix them.
- */
- if (strncmp (Fname, COUR, strlen (COUR)) != 0)
- message (0, _("couldn't open AFM file for font \"%s\", using default\n"),
- Fname);
- error = afm_open_default_font (afm, &font);
- if (error != AFM_SUCCESS)
- {
- afm_error_to_string (error, buf);
- fatal (_("couldn't open AFM file for the default font: %s"),
- buf);
- }
- }
-
- /* Apply encoding. */
- switch (encoding)
- {
- case ENC_LATIN1:
- (void) afm_font_encoding (font, AFM_ENCODING_LATIN1, enc_flags);
- break;
-
- case ENC_LATIN2:
- (void) afm_font_encoding (font, AFM_ENCODING_LATIN2, enc_flags);
- break;
-
- case ENC_LATIN3:
- (void) afm_font_encoding (font, AFM_ENCODING_LATIN3, enc_flags);
- break;
-
- case ENC_ASCII:
- (void) afm_font_encoding (font, AFM_ENCODING_ASCII, enc_flags);
- break;
-
- case ENC_ASCII_SCANDS:
- /* First apply standard 7bit ASCII encoding. */
- (void) afm_font_encoding (font, AFM_ENCODING_ASCII, enc_flags);
-
- /* Then add those scand characters. */
- for (i = 0; enc_7bit_ascii_scands[i].name; i++)
- (void) afm_font_encode (font, enc_7bit_ascii_scands[i].code,
- enc_7bit_ascii_scands[i].name, enc_flags);
- break;
-
- case ENC_IBMPC:
- (void) afm_font_encoding (font, AFM_ENCODING_IBMPC, enc_flags);
- break;
-
- case ENC_MAC:
- (void) afm_font_encoding (font, AFM_ENCODING_MAC, enc_flags);
- break;
-
- case ENC_VMS:
- (void) afm_font_encoding (font, AFM_ENCODING_VMS, enc_flags);
- break;
-
- case ENC_HP8:
- (void) afm_font_encoding (font, AFM_ENCODING_HP8, enc_flags);
- break;
-
- case ENC_PS:
- /* Let's use font's default encoding -- nothing here. */
- break;
- }
-
- /* Store font information to the AFM cache. */
- if (!strhash_put (afm_cache, Fname, strlen (Fname), font, NULL))
- cached = 0;
- }
-
- /* Read character widths and types. */
- for (i = 0; i < 256; i++)
- {
- AFMNumber w0x, w0y;
-
- (void) afm_font_charwidth (font, Fpt, (unsigned int) i, &w0x, &w0y);
- font_widths[i] = w0x;
-
- if (font->encoding[i] == AFM_ENC_NONE)
- font_ctype[i] = ' ';
- else if (font->encoding[i] == AFM_ENC_NON_EXISTENT)
- font_ctype[i] = '.';
- else
- font_ctype[i] = '*';
- }
-
- font_is_fixed = font->writing_direction_metrics[0].IsFixedPitch;
- font_bbox_lly = font->global_info.FontBBox_lly;
-
- if (!cached)
- (void) afm_close_font (font);
- }
-
-
- void
- download_font (char *name)
- {
- AFMError error;
- const char *prefix;
- struct stat stat_st;
- char fname[512];
- unsigned char buf[4096];
- FILE *fp;
- int i;
- char *cp;
-
- /* Get font prefix. */
- error = afm_font_prefix (afm, name, &prefix);
- if (error != AFM_SUCCESS)
- /* Font is unknown, nothing to download. */
- return;
-
- /* Check if we have a font description file. */
-
- /* .pfa */
- sprintf (fname, "%s.pfa", prefix);
- if (stat (fname, &stat_st) != 0)
- {
- /* .pfb */
- sprintf (fname, "%s.pfb", prefix);
- if (stat (fname, &stat_st) != 0)
- /* Couldn't find font description file, nothing to download. */
- return;
- }
-
- /* Ok, fine. Font was found. */
-
- message (1, _("downloading font \"%s\"\n"), name);
- fp = fopen (fname, "rb");
- if (fp == NULL)
- {
- message (0, _("couldn't open font description file \"%s\": %s\n"),
- fname, strerror (errno));
- return;
- }
-
- /* Dump file. */
- fprintf (ofp, "%%%%BeginResource: font %s\n", name);
-
- /* Check file type. */
- i = fgetc (fp);
- if (i == EOF)
- {
- /* Not much to do here. */
- ;
- }
- else if (i == 128)
- {
- int done = 0;
- unsigned int chunk;
- unsigned int to_read;
- int last_was_cr;
- int j;
-
- /* IBM PC Format */
-
- ungetc (i, fp);
-
- while (!done)
- {
- /* Read 6-byte long header. */
- i = fread (buf, 1, 6, fp);
- if (i != 6)
- break;
-
- chunk = buf[2] | (buf[3] << 8) | (buf[4] << 16) | (buf[5] << 24);
-
- /* Check chunk type. */
- switch (buf[1])
- {
- case 1: /* ASCII */
- last_was_cr = 0;
- while (chunk > 0)
- {
- to_read = sizeof (buf) < chunk ? sizeof (buf) : chunk;
- i = fread (buf, 1, to_read, fp);
- if (i == 0)
- {
- done = 1;
- break;
- }
-
- /* Check and fix Mac-newlines. */
- for (j = 0; j < i; j++)
- {
- if (j == 0 && last_was_cr && buf[0] != '\n')
- {
- fputc ('\n', ofp);
- fputc (buf[0], ofp);
- }
- else if (buf[j] == '\r' && j + 1 < i
- && buf[j + 1] != '\n')
- {
- fputc ('\n', ofp);
- }
- else if (buf[j] != '\r')
- fputc (buf[j], ofp);
- }
-
- chunk -= i;
- last_was_cr = (buf[i - 1] == '\r');
- }
- break;
-
- case 2: /* binary data */
- while (chunk > 0)
- {
- to_read = sizeof (buf) < chunk ? sizeof (buf) : chunk;
- i = fread (buf, 1, to_read, fp);
- if (i == 0)
- {
- done = 1;
- break;
- }
-
- for (j = 0; j < i; j++)
- {
- fprintf (ofp, "%02X", buf[j]);
- if ((j + 1) % 32 == 0)
- fprintf (ofp, "\n");
- }
- chunk -= i;
- }
- break;
-
- case 3: /* EOF */
- done = 1;
- break;
- }
-
- /* Force a linebreak after each chunk. */
- fprintf (ofp, "\n");
- }
- }
- else
- {
- /* Plain ASCII. */
- ungetc (i, fp);
- while ((i = fread (buf, 1, sizeof (buf), fp)) != 0)
- fwrite (buf, 1, i, ofp);
- }
-
- fprintf (ofp, "%%%%EndResource\n");
-
- /* Remove font from needed resources. */
- (void) strhash_delete (res_fonts, name, strlen (name) + 1, (void **) &cp);
-
- fclose (fp);
- }
-
-
- char *
- escape_string (char *string)
- {
- int i, j;
- int len;
- char *cp;
-
- /* Count the length of the result string. */
- for (len = 0, i = 0; string[i]; i++)
- switch (string[i])
- {
- case '(':
- case ')':
- case '\\':
- len += 2;
- break;
-
- default:
- len++;
- }
-
- /* Create result. */
- cp = xmalloc (len + 1);
- for (i = 0, j = 0; string[i]; i++)
- switch (string[i])
- {
- case '(':
- case ')':
- case '\\':
- cp[j++] = '\\';
- /* FALLTHROUGH */
-
- default:
- cp[j++] = string[i];
- break;
- }
- cp[j++] = '\0';
-
- return cp;
- }
-
-
-
- /*
- * Help macros for the format_user_string() function.
- */
-
- #define NEED_NBYTES(n) \
- do { \
- if (rbufpos + (n) >= rbuflen) \
- { \
- rbuflen += (n) + 1024; \
- rbuf = xrealloc (rbuf, rbuflen); \
- } \
- } while (0)
-
- #define APPEND_CH(ch) \
- do { \
- NEED_NBYTES (1); \
- rbuf[rbufpos++] = (ch); \
- } while (0)
-
- #define APPEND_STR(str) \
- do { \
- int len = strlen ((str)); \
- NEED_NBYTES (len); \
- memcpy (rbuf + rbufpos, str, len); \
- rbufpos += len; \
- } while (0)
-
- char *
- format_user_string (char *str)
- {
- char *cp;
- char *rbuf = NULL;
- int rbuflen = 0;
- int rbufpos = 0;
- int i = 0;
- int j;
- char buf[512];
- char buf2[512];
-
- /* Format string. */
- for (i = 0; str[i] != '\0'; i++)
- {
- switch (str[i])
- {
- case '%': /* general state related `%' escapes */
- i++;
- switch (str[i])
- {
- case '%': /* `%%' character `%' */
- APPEND_CH ('%');
- break;
-
- case 'c': /* `%c' trailing component of pwd. */
- getcwd (buf, sizeof (buf));
- cp = strrchr (buf, '/');
- if (cp)
- cp++;
- else
- cp = buf;
- APPEND_STR (cp);
- break;
-
- case 'C': /* `%C' runtime in `hh:mm:ss' format */
- sprintf (buf, "%02d:%02d:%02d", run_tm.tm_hour, run_tm.tm_min,
- run_tm.tm_sec);
- APPEND_STR (buf);
- break;
-
- case 'd': /* `%d' current working directory */
- getcwd (buf, sizeof (buf));
- APPEND_STR (buf);
- break;
-
- case 'D':
- if (str[i + 1] == '{')
- {
- /* `%D{}' format run date with strftime() */
- for (j = 0, i += 2;
- j < sizeof (buf2) && str[i] && str[i] != '}';
- i++, j++)
- buf2[j] = str[i];
- if (str[i] != '}')
- fatal (_("%%Format: too long format for %%D{} escape"));
-
- buf2[j] = '\0';
- strftime (buf, sizeof (buf), buf2, &run_tm);
- }
- else
- {
- /* `%D' run date in `yy-mm-dd' format */
- sprintf (buf, "%02d-%02d-%02d", run_tm.tm_year,
- run_tm.tm_mon + 1, run_tm.tm_mday);
- }
- APPEND_STR (buf);
- break;
-
- case 'E': /* `%E' run date in `yy/mm/dd' format */
- sprintf (buf, "%02d/%02d/%02d", run_tm.tm_year,
- run_tm.tm_mon + 1, run_tm.tm_mday);
- APPEND_STR (buf);
- break;
-
- case 'F': /* `%F' run date in `dd.mm.yyyy' format */
- sprintf (buf, "%d.%d.%d",
- run_tm.tm_mday,
- run_tm.tm_mon + 1,
- run_tm.tm_year+1900);
- APPEND_STR (buf);
- break;
-
- case 'H': /* `%H' document title */
- APPEND_STR (title);
- break;
-
- case 'm': /* `%m' the hostname up to the first `.' */
- (void) gethostname (buf, sizeof (buf));
- cp = strchr (buf, '.');
- if (cp)
- *cp = '\0';
- APPEND_STR (buf);
- break;
-
- case 'M': /* `%M' the full hostname */
- (void) gethostname (buf, sizeof (buf));
- APPEND_STR (buf);
- break;
-
- case 'n': /* `%n' username */
- APPEND_STR (passwd->pw_name);
- break;
-
- case 'N': /* `%N' pw_gecos up to the first `,' char */
- strcpy (buf, passwd->pw_gecos);
- cp = strchr (buf, ',');
- if (cp)
- *cp = '\0';
- APPEND_STR (buf);
- break;
-
- case 't': /* `%t' runtime in 12-hour am/pm format */
- sprintf (buf, "%d:%d%s",
- run_tm.tm_hour > 12
- ? run_tm.tm_hour - 12 : run_tm.tm_hour,
- run_tm.tm_min,
- run_tm.tm_hour > 12 ? "pm" : "am");
- APPEND_STR (buf);
- break;
-
- case 'T': /* `%T' runtime in 24-hour format */
- sprintf (buf, "%d:%d", run_tm.tm_hour, run_tm.tm_min);
- APPEND_STR (buf);
- break;
-
- case '*': /* `%*' runtime in 24-hour format with secs */
- sprintf (buf, "%d:%d:%d", run_tm.tm_hour, run_tm.tm_min,
- run_tm.tm_sec);
- APPEND_STR (buf);
- break;
-
- case 'W': /* `%W' run date in `mm/dd/yy' format */
- sprintf (buf, "%02d/%02d/%02d", run_tm.tm_mon + 1,
- run_tm.tm_mday, run_tm.tm_year);
- APPEND_STR (buf);
- break;
-
- default:
- fatal (_("%%Format: unknown `%%' escape `%c' (%d)"),
- str[i], str[i]);
- break;
- }
- break;
-
- case '$': /* input file related `$' escapes */
- i++;
- switch (str[i])
- {
- case '$': /* `$$' character `$' */
- APPEND_CH ('$');
- break;
-
- case '%': /* `$%' current page number */
- sprintf (buf, "%d", current_pagenum);
- APPEND_STR (buf);
- break;
-
- case '=': /* `$=' number of pages in this file */
- APPEND_CH ('\001');
- break;
-
- case '(': /* $(ENVVAR) */
- for (j = 0, i++;
- str[i] && str[i] != ')' && j < sizeof (buf) - 1;
- i++)
- buf[j++] = str[i];
-
- if (str[i] == '\0')
- fatal (_("%%Format: no closing ')' for $() escape"));
- if (str[i] != ')')
- fatal (_("%%Format: too long variable name for $() escape"));
-
- buf[j] = '\0';
-
- cp = getenv (buf);
- if (cp == NULL)
- cp = "";
- APPEND_STR (cp);
- break;
-
- case 'C': /* `$C' modtime in `hh:mm:ss' format */
- sprintf (buf, "%02d:%02d:%02d", mod_tm.tm_hour,
- mod_tm.tm_min, mod_tm.tm_sec);
- APPEND_STR (buf);
- break;
-
- case 'D':
- if (str[i + 1] == '{')
- {
- /* `$D{}' format modification date with strftime() */
- for (j = 0, i += 2;
- j < sizeof (buf2) && str[i] && str[i] != '}';
- i++, j++)
- buf2[j] = str[i];
- if (str[i] != '}')
- fatal (_("%%Format: too long format for $D{} escape"));
-
- buf2[j] = '\0';
- strftime (buf, sizeof (buf), buf2, &mod_tm);
- }
- else
- {
- /* `$D' mod date in `yy-mm-dd' format */
- sprintf (buf, "%02d-%02d-%02d", mod_tm.tm_year,
- mod_tm.tm_mon + 1, mod_tm.tm_mday);
- }
- APPEND_STR (buf);
- break;
-
- case 'E': /* `$E' mod date in `yy/mm/dd' format */
- sprintf (buf, "%02d/%02d/%02d", mod_tm.tm_year,
- mod_tm.tm_mon + 1, mod_tm.tm_mday);
- APPEND_STR (buf);
- break;
-
- case 'F': /* `$F' run date in `dd.mm.yyyy' format */
- sprintf (buf, "%d.%d.%d",
- mod_tm.tm_mday,
- mod_tm.tm_mon + 1,
- mod_tm.tm_year+1900);
- APPEND_STR (buf);
- break;
-
- case 't': /* `$t' runtime in 12-hour am/pm format */
- sprintf (buf, "%d:%d%s",
- mod_tm.tm_hour > 12
- ? mod_tm.tm_hour - 12 : mod_tm.tm_hour,
- mod_tm.tm_min,
- mod_tm.tm_hour > 12 ? "pm" : "am");
- APPEND_STR (buf);
- break;
-
- case 'T': /* `$T' runtime in 24-hour format */
- sprintf (buf, "%d:%d", mod_tm.tm_hour, mod_tm.tm_min);
- APPEND_STR (buf);
- break;
-
- case '*': /* `$*' runtime in 24-hour format with secs */
- sprintf (buf, "%d:%d:%d", mod_tm.tm_hour, mod_tm.tm_min,
- mod_tm.tm_sec);
- APPEND_STR (buf);
- break;
-
- case 'W': /* `$W' run date in `mm/dd/yy' format */
- sprintf (buf, "%02d/%02d/%02d", mod_tm.tm_mon + 1,
- mod_tm.tm_mday, mod_tm.tm_year);
- APPEND_STR (buf);
- break;
-
- default:
- fatal (_("%%Format: unknown `$' escape `%c' (%d)"),
- str[i], str[i]);
- break;
- }
- break;
-
- default:
- APPEND_CH (str[i]);
- break;
- }
- }
- APPEND_CH ('\0');
-
- /* Escape PS specials. */
- cp = escape_string (rbuf);
- xfree (rbuf);
-
- return cp;
- }
-
-
- void
- parse_key_value_pair (StringHashPtr set, char *kv)
- {
- char *cp;
- char key[256];
-
- cp = strchr (kv, ':');
- if (cp == NULL)
- {
- if (strhash_delete (set, kv, strlen (kv) + 1, (void **) &cp))
- xfree (cp);
- }
- else
- {
- sprintf (key, "%.*s", cp - kv, kv);
- strhash_put (set, key, strlen (key) + 1, xstrdup (cp + 1),
- (void **) &cp);
- if (cp)
- xfree (cp);
- }
- }
-
-
- int
- count_key_value_set (StringHashPtr set)
- {
- int i = 0, got, j;
- char *cp;
- void *value;
-
- for (got = strhash_get_first (set, &cp, &j, &value); got;
- got = strhash_get_next (set, &cp, &j, &value))
- i++;
-
- return i;
- }
-
-
- int
- pathwalk (char *path, PathWalkProc proc, void *context)
- {
- char buf[512];
- char *cp;
- char *cp2;
- int len, i;
-
- for (cp = path; cp; cp = strchr (cp, PATH_SEPARATOR))
- {
- if (cp != path)
- cp++;
-
- cp2 = strchr (cp, PATH_SEPARATOR);
- if (cp2)
- len = cp2 - cp;
- else
- len = strlen (cp);
-
- memcpy (buf, cp, len);
- buf[len] = '\0';
-
- i = (*proc) (buf, context);
- if (i != 0)
- return i;
- }
-
- return 0;
- }
-
-
- int
- file_lookup (char *path, void *context)
- {
- int len;
- FileLookupCtx *ctx = context;
- struct stat stat_st;
- int i;
-
- message (2, "file_lookup(): %s/%s%s\t", path, ctx->name,
- ctx->suffix);
-
- len = strlen (path);
- if (len && path[len - 1] == '/')
- len--;
-
- sprintf (ctx->fullname, "%.*s/%s%s", len, path, ctx->name, ctx->suffix);
-
- i = stat (ctx->fullname, &stat_st) == 0;
-
- message (2, "#%c\n", i ? 't' : 'f');
- return i;
- }
-
-
- void
- tilde_subst (char *from, char *to)
- {
- char *cp;
- char user[256];
- int i, j;
- struct passwd *pswd;
-
- if (from[0] != '~')
- {
- copy_out:
- strcpy (to, from);
- return;
- }
-
- if (from[1] == '/' || from[1] == '\0')
- {
- cp = getenv ("HOME");
- if (cp == NULL)
- goto copy_out;
-
- sprintf (to, "%s%s", cp, from + 1);
- return;
- }
-
- /* Get user's login name. */
- for (i = 1, j = 0; from[i] && from[i] != '/'; i++)
- user[j++] = from[i];
- user[j++] = '\0';
-
- pswd = getpwnam (user);
- if (pswd)
- {
- /* Found passwd entry. */
- sprintf (to, "%s%s", pswd->pw_dir, from + i);
- return;
- }
-
- /* No match found. */
- goto copy_out;
- }
-
-
- double
- parse_float (char *string, int units, int horizontal)
- {
- double val;
- char *end;
-
- val = strtod (string, &end);
- if (end == string)
- malformed_float:
- error (_("malformed float dimension: \"%s\""), string);
-
- if (units)
- {
- switch (*end)
- {
- case 'c':
- val *= 72 / 2.54;
- break;
-
- case 'p':
- break;
-
- case 'i':
- val *= 72;
- break;
-
- case '\0':
- /* FALLTHROUGH */
-
- case 'l':
- if (horizontal)
- val *= CHAR_WIDTH ('m');
- else
- val *= LINESKIP;
- break;
-
- default:
- goto malformed_float;
- break;
- }
- }
- else
- {
- if (*end != '\0')
- goto malformed_float;
- }
-
- return val;
- }
-
-
- /*
- * InputStream functions.
- */
-
- int
- is_open (InputStream *is, FILE *fp, char *fname, char *input_filter)
- {
- /* Init stream variables. */
- is->data_in_buf = 0;
- is->bufpos = 0;
- is->nreads = 0;
- is->unget_ch = EOF;
-
- /* Input filter? */
- if (input_filter)
- {
- char *cmd = NULL;
- int cmdlen;
- int i, pos;
-
- is->is_pipe = 1;
-
- if (fname == NULL)
- fname = input_filter_stdin;
-
- /*
- * Count the initial command length, this will grow dynamically
- * when file specifier `%s' is encountered from <input_filter>.
- */
- cmdlen = strlen (input_filter) + 1;
- cmd = xmalloc (cmdlen);
-
- /* Create filter command. */
- pos = 0;
- for (i = 0; input_filter[i]; i++)
- {
- if (input_filter[i] == '%')
- {
- switch (input_filter[i + 1])
- {
- case 's':
- /* Expand cmd-buffer. */
- cmdlen += strlen (fname);
- cmd = xrealloc (cmd, cmdlen);
-
- /* Paste filename. */
- strcpy (cmd + pos, fname);
- pos += strlen (fname);
-
- i++;
- break;
-
- case '%':
- cmd[pos++] = '%';
- i++;
- break;
-
- default:
- cmd[pos++] = input_filter[i];
- break;
- }
- }
- else
- cmd[pos++] = input_filter[i];
- }
- cmd[pos++] = '\0';
-
- is->fp = popen (cmd, "r");
- xfree (cmd);
-
- if (is->fp == NULL)
- {
- error (_("couldn't open input filter \"%s\" for file \"%s\": %s"),
- input_filter, fname ? fname : "(stdin)",
- strerror (errno));
- return 0;
- }
- }
- else
- {
- /* Just open the stream. */
- is->is_pipe = 0;
- if (fp)
- is->fp = fp;
- else
- {
- is->fp = fopen (fname, "rb");
- if (is->fp == NULL)
- {
- error (_("couldn't open input file \"%s\": %s"), fname,
- strerror (errno));
- return 0;
- }
- }
- }
-
- return 1;
- }
-
-
- void
- is_close (InputStream *is)
- {
- if (is->is_pipe)
- pclose (is->fp);
- else
- fclose (is->fp);
- }
-
-
- int
- is_getc (InputStream *is)
- {
- int ch;
-
- if (is->unget_ch != EOF)
- {
- ch = is->unget_ch;
- is->unget_ch = EOF;
- return ch;
- }
-
- retry:
-
- /* Do we have any data left? */
- if (is->bufpos >= is->data_in_buf)
- {
- /* At the EOF? */
- if (is->nreads > 0 && is->data_in_buf < sizeof (is->buf))
- /* Yes. */
- return EOF;
-
- /* Read more data. */
- is->data_in_buf = fread (is->buf, 1, sizeof (is->buf), is->fp);
- is->bufpos = 0;
- is->nreads++;
-
- goto retry;
- }
-
- return is->buf[is->bufpos++];
- }
-
-
- int
- is_ungetc (int ch, InputStream *is)
- {
- is->unget_ch = ch;
- return 1;
- }
-
-
- /*
- * Static functions.
- */
-
- static void
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- cfg_fatal (char *file, int line, char *fmt, ...)
- #else
- cfg_fatal (file, line, va_alist)
- char *file;
- int line;
- va_dcl
- #endif
- {
- va_list args;
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- va_start (args, fmt);
- #else
- char *fmt;
-
- va_start (args);
- fmt = va_arg (args, char *);
- #endif
-
- fprintf (stderr, "%s:%s:%d: ", program, file, line);
-
- #ifdef HAVE_VPRINTF
- vfprintf (stderr, fmt, args);
- #else
- _doprnt (fmt, args, stderr);
- #endif
- va_end (args);
-
- fprintf (stderr, "\n");
- fflush (stderr);
-
- exit (1);
- }
-